/*
 * Copyright 2013 Agustina Martinez-Garcia

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
 */
package uk.ljmu.qudexapps.xmllib.services;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.Node;
import org.igfay.jfig.JFig;
import org.igfay.jfig.JFigException;
import org.mulgara.query.QueryException;

import uk.ljmu.fedoraifz.restrequests.FedoraOperationsAPIM;
import uk.ljmu.fedoraifz.restrequests.FedoraOperationsAPIMImpl;
import uk.ljmu.metadata.utilities.MetadataUtilities;
import uk.ljmu.mulgaraifz.errorhandling.MulgaraException;
import uk.ljmu.mulgaraifz.httprequests.MulgaraOperations;
import uk.ljmu.mulgaraifz.httprequests.MulgaraOperationsImpl;
import uk.ljmu.mulgaraifz.mulgarainference.model.MulgaraOpResults;
import uk.ljmu.mulgaraifz.mulgarainference.services.MulgaraGraphService;
import uk.ljmu.mulgaraifz.mulgarainference.services.MulgaraGraphServiceImpl;
import uk.ljmu.mulgaraifz.mulgarainference.utilities.Constants;
import uk.ljmu.mulgaraifz.sparql.QueryConstants;
import uk.ljmu.mulgaraifz.utilities.XmlTraverse;
import uk.ljmu.qudexapps.xmllib.exceptions.FedoraException;
import uk.ljmu.qudexapps.xmllib.exceptions.GraphException;
import uk.ljmu.qudexapps.xmllib.model.CollectionElement;
import uk.ljmu.qudexapps.xmllib.model.GraphInformation;

public class FedoraMulgaraServiceImpl implements FedoraMulgaraService {
    private static Logger log = Logger
	    .getLogger(FedoraMulgaraServiceImpl.class);
    private static final String GRAPH_PREFIX = "graph";
    private static final String FEDORA_ID_PREFIX = "info:fedora";
    private static final Map<String, String> RESERVED_PREFIXES = new HashMap<String, String>();
    static {
	// Reserved Dublin Core datastream
	RESERVED_PREFIXES.put("DC", "DC");
	// Reserved External Relationships datastream
	RESERVED_PREFIXES.put("EXT", "RELS-EXT");
	// Reserved Internal Relationships datastream
	RESERVED_PREFIXES.put("INT", "RELS-INT");
    }
	//AMG SEPT 2013
	public static String GET_CATEGORY_PID;
    // Queries over Qudex Collections and Documents
    /**
     * Obtains all the collections in the repository that are containers, this collections 
     * must not present the datastream QudexInstance therefore one can reedit them and add more
     * documents or collections.
     */
    public static String GET_QUDEX_ROOTCOLLECTIONS;
    /**
     * This query presents the collection hierarchy of the current collection which the useris working with
     */
    public static String GET_QUDEX_COLLECTIONS_WORKING;
    /**
     * 
     */
    public static String GET_QUDEX_ROOTCOLLECTIONSTITLE;
    /**
     * Obtain ID and DATASTREAM NAME of all the object within a particular
     * namespace that present and Inline XML or RDF datastream
     */
    public static String QUDEX_CONTAINS_INSTANCE;

    public static String GET_QUDEX_ALLCOLLECTIONS;

    public static String GET_QUDEX_IS_SUBCOLLECTION;

    public static String GET_QUDEX_SUBCOLLECTION_ROOT_PARENT;

    public static String GET_IMMEDIATE_COLLECTION_PARENT;
    
    public static String GET_COLLECTIONS_ONE_QUERY;
    
	private static String QUDEX_GET_FILES;
	
	private static String QUDEX_GET_OBJ_TITLE;

    static {
	StringBuilder sb = new StringBuilder();
	sb.append("PREFIX dc: <http://purl.org/dc/elements/1.1/> ");
	sb
		.append("PREFIX rel: <info:fedora/fedora-system:def/relations-external#> ");
	sb.append("PREFIX dcmitype: <http://purl.org/dc/dcmitype/> ");
	sb.append("PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> ");
	sb.append("SELECT ?col ");
	sb.append("FROM $GRAPH$ ");
	sb.append("WHERE { ");
	sb.append("?col <rdf:type> <dcmitype:Collection>. ");
	sb.append("optional { ?col <rel:isPartOf> ?col2. } ");
	sb
		.append("filter (!bound(?col2) && regex(str(?col), \".*$PREFIX$:.*\", \"i\")). ");
	sb.append("} ");
	GET_QUDEX_ROOTCOLLECTIONS = sb.toString();
	sb.delete(0, sb.toString().length());
	
	sb.append("ASK FROM $GRAPH$ { <$COLID$> <info:fedora/fedora-system:def/view#disseminates> <$COLID$/QudexInstance>}");
	QUDEX_CONTAINS_INSTANCE = sb.toString();
	sb.delete(0, sb.toString().length());
	
	sb.append("PREFIX dc: <http://purl.org/dc/elements/1.1/> ");
	sb
		.append("PREFIX rel: <info:fedora/fedora-system:def/relations-external#> ");
	sb.append("PREFIX dcmitype: <http://purl.org/dc/dcmitype/> ");
	sb.append("PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> ");
	sb.append("SELECT ?col ?title ");
	sb.append("FROM $GRAPH$ ");
	sb.append("WHERE { ");
	sb.append("?col <rdf:type> <dcmitype:Collection>. ");
	sb.append("?col <dc:title> ?title. ");
	sb.append("optional { ?col <rel:isPartOf> ?col2. } ");
	sb
		.append("filter (!bound(?col2) && regex(str(?col), \".*$PREFIX$:.*\", \"i\")). ");
	sb.append("} ");
	GET_QUDEX_ROOTCOLLECTIONSTITLE = sb.toString();
	sb.delete(0, sb.toString().length());

	sb.append("PREFIX dc: <http://purl.org/dc/elements/1.1/> ");
	sb
		.append("PREFIX rel: <info:fedora/fedora-system:def/relations-external#> ");
	sb.append("PREFIX dcmitype: <http://purl.org/dc/dcmitype/> ");
	sb.append("PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> ");
	sb.append("SELECT ?col ?title ");
	sb.append("FROM $GRAPH$ ");
	sb.append("WHERE { ");
	sb.append("?col <dc:title> ?title. ");
	sb.append("?col <rdf:type> <dcmitype:Collection>. ");
	sb.append("filter (regex(str(?col), \".*$PREFIX$:.*\", \"i\")). ");
	sb.append("} ");
	GET_QUDEX_ALLCOLLECTIONS = sb.toString();
	sb.delete(0, sb.toString().length());
	
	sb.append("PREFIX dc: <http://purl.org/dc/elements/1.1/> ");
	sb
		.append("PREFIX rel: <info:fedora/fedora-system:def/relations-external#> ");
	sb.append("PREFIX dcmitype: <http://purl.org/dc/dcmitype/> ");
	sb.append("PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> ");
	sb.append("SELECT ?col ?title ");
	sb.append("FROM $GRAPH$ ");
	sb.append("WHERE { ");
	sb.append("?col <dc:title> ?title. ");
	sb.append("?col <rdf:type> <dcmitype:Collection>. ");
	sb.append("?col <rel:isPartOf>+ $WORKCOL$ ");
	sb.append("filter (regex(str(?col), \".*$PREFIX$:.*\", \"i\")). ");
	sb.append("} ");
	GET_QUDEX_COLLECTIONS_WORKING = sb.toString();
	sb.delete(0, sb.toString().length());

	sb.append("PREFIX rel: <info:fedora/fedora-system:def/relations-external#> ");
	sb.append("ASK FROM $GRAPH$ {$COL_ID$ <rel:isPartOf> ?o}");
	GET_QUDEX_IS_SUBCOLLECTION = sb.toString();
	sb.delete(0, sb.toString().length());

	sb.append("PREFIX dc: <http://purl.org/dc/elements/1.1/> ");
	sb.append("PREFIX rel: <info:fedora/fedora-system:def/relations-external#> ");
	sb.append("PREFIX dcmitype: <http://purl.org/dc/dcmitype/> ");
	sb.append("PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> ");
	sb.append("SELECT distinct ?root ");
	sb.append("FROM $GRAPH$ ");
	sb.append("{ ");
	sb.append("$COL_ID$ <dc:identifier> ?id; ");
	sb.append("<rdf:type> <dcmitype:Collection>; ");
	sb.append("<rel:isPartOf>+ ?root. ");
	sb.append("optional { ?root <rel:isPartOf> ?col2. } ");
	sb.append("filter (!bound(?col2)) ");
	sb.append("filter (regex(str(?id), '$PREFIX$:.*')) ");
	sb.append("} ");
	GET_QUDEX_SUBCOLLECTION_ROOT_PARENT = sb.toString();
	sb.delete(0, sb.toString().length());
	
	sb.append("PREFIX rel: <info:fedora/fedora-system:def/relations-external#> ");
	sb.append("PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> ");
	sb.append("PREFIX dcmitype: <http://purl.org/dc/dcmitype/> ");
	sb.append("SELECT ?subject ");
	sb.append("FROM $GRAPH$ ");
	sb.append("WHERE { ");
	sb.append("$COL_ID$ <rel:isPartOf> ?subject. ");
	sb.append("?subject <rdf:type> <dcmitype:Collection>. ");
	sb.append("} ");
	GET_IMMEDIATE_COLLECTION_PARENT = sb.toString();
	sb.delete(0, sb.toString().length());
	
	// AMG TO GENERATE COLLECTIONS/SUB-COLLECTIONS TREE QUERY 
	sb.append("PREFIX dc: <http://purl.org/dc/elements/1.1/> ");
	sb.append("PREFIX rel: <info:fedora/fedora-system:def/relations-external#> ");
	sb.append("PREFIX dcmitype: <http://purl.org/dc/dcmitype/> ");
	sb.append("PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> ");
	sb.append("SELECT distinct ?id ?col ?child ?title ");
	sb.append("FROM $GRAPH$ ");
	sb.append("{ ");
	sb.append("?s <dc:identifier> ?id.");
	sb.append("?s <dc:title> ?title.");
	sb.append("?s <rdf:type> <dcmitype:Collection>. ");
	sb.append("optional { ?s <dc:identifier> ?id. ");
	sb.append("optional { ?s <rel:isPartOf> ?col. }");
	sb.append("optional { ?child <rdf:type> <dcmitype:Collection>. optional {?child <rel:isPartOf> ?s.}}} ");
	sb.append("filter (regex(str(?id), '$PREFIX$.*')) ");
	sb.append("} ");
	GET_COLLECTIONS_ONE_QUERY = sb.toString();
	sb.delete(0, sb.toString().length());
	
	sb.append("PREFIX dc: <http://purl.org/dc/elements/1.1/>");
	sb.append("PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> ");
	sb.append("PREFIX rel: <info:fedora/fedora-system:def/relations-external#> ");
	sb.append("SELECT ?id ?title ");
	sb.append("FROM $GRAPH$ ");
	sb.append("WHERE { ");
	sb.append("?id a <http://example.org/File>; ");
	sb.append("	rel:isPartOf <$COL_ID$>.");
	sb.append("optional { ?id dc:title ?title. } "); 
	sb.append("}");
	QUDEX_GET_FILES = sb.toString();
	sb.delete(0,  QUDEX_GET_FILES.length());
	
	sb.append("PREFIX dc: <http://purl.org/dc/elements/1.1/>");
	sb.append("SELECT ?title ");
	sb.append("FROM $GRAPH$ ");
	sb.append("WHERE { ");
	sb.append("<$OBJ_ID$> dc:title ?title. "); 
	sb.append("}");
	QUDEX_GET_OBJ_TITLE = sb.toString();
	sb.delete(0,  QUDEX_GET_OBJ_TITLE.length());
	
	sb.append("PREFIX dc: <http://purl.org/dc/elements/1.1/> ");
	sb.append("PREFIX rel: <info:fedora/fedora-system:def/relations-external#> ");
	sb.append("PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> ");
	sb.append("SELECT ?id ");
	sb.append("FROM $GRAPH$");
	sb.append("WHERE { ");
	sb.append("?cat dc:identifier ?id; ");
	sb.append("rdfs:label '$CAT_LABEL$'; ");
	sb.append("rel:isPartOf ?col1. ");
	sb.append("FILTER (regex(str(?id), '.*$COL_PREFIX$.*') && (str(?col1) = 'info:fedora/$COL_ID$')) ");
	sb.append("} ");
	GET_CATEGORY_PID = sb.toString();
	sb.delete(0,  GET_CATEGORY_PID.length());
	
    }
    /**
     * Fedora Object to operate in the repository
     */
    private FedoraOperationsAPIM fedObject;
    /**
     * GraphInformation instance to manage results from the operations in Fedora
     * and the triplestore
     */
    private List<GraphInformation> graphInfo;
    /**
     * Mulgara Object to operate in the triplestore
     */
    private MulgaraOperations mulgObject;
    /**
     * Holds the root collection parent of a given sub-collection
     */
    private String rootCollectionPid;

    /**
     * @return the mulgObject
     */
    public MulgaraOperations getMulgObject() {
	return mulgObject;
    }

    /**
     * @param rootCollectionPid
     *            the rootCollectionPid to set
     */
    public void setRootCollectionPid(String rootCollectionPid) {
	this.rootCollectionPid = rootCollectionPid;
    }

    /**
     * @return the rootCollectionPid
     */
    public String getRootCollectionPid() {
	return rootCollectionPid;
    }

    public void setGraphInfo(List<GraphInformation> graphInfo) {
	this.graphInfo = graphInfo;
    }

    public List<GraphInformation> getGraphInfo() {
	return graphInfo;
    }

    /**
     * @return the fedObject
     */
    public FedoraOperationsAPIM getFedObject() {
	return fedObject;
    }

    // CONSTRUCTORS
    public FedoraMulgaraServiceImpl() throws JFigException {
	log.setLevel(Logger.getRootLogger().getLevel());
	try {
	    mulgObject = new MulgaraOperationsImpl();
	} catch (MulgaraException e) {
	    log.fatal(e.getMessage());
	}
	fedObject = new FedoraOperationsAPIMImpl();
	this.graphInfo = new ArrayList<GraphInformation>();
	log.info("Graph Operations initialised");
    }
    
    public FedoraMulgaraServiceImpl(String username, String password) throws JFigException {
	log.setLevel(Logger.getRootLogger().getLevel());
	try {
	    mulgObject = new MulgaraOperationsImpl();
	} catch (MulgaraException e) {
	    log.fatal(e.getMessage());
	}
	fedObject = new FedoraOperationsAPIMImpl(username, password);
	this.graphInfo = new ArrayList<GraphInformation>();
	log.info("Graph Operations initialised");
    }

    // OPERATIONS
    /**
     * @param colidentifier
     * @return
     * @throws GraphException
     * @throws MulgaraException
     * @throws JFigException
     * @throws FedoraException
     */
    public void createGraphByCollection(String colidentifier)
	    throws JFigException, MulgaraException, GraphException,
	    FedoraException {
	List<String> collectionObjectsList;
	// Initialize array of identifiers
	ArrayList<String> arrayId = new ArrayList<String>();

	collectionObjectsList = this.getLoopIDbyCollection(mulgObject,
		colidentifier);

	String graphName = "";
	try {
	    graphName = JFig.getInstance()
		    .getValue("mulgaraServer", "graphURL")
		    + GRAPH_PREFIX;
	} catch (JFigException e) {
	    log.fatal(e.getMessage());
	    throw new GraphException(e.getMessage());
	}

	if (colidentifier.contains("info:fedora")) {
	    String temp = colidentifier.replace("info:fedora/", "");
	    graphName += temp;
	} else
	    graphName += colidentifier;

	for (String pairString : collectionObjectsList) {
	    String[] pair = pairString.split(";");
	    String idData = pair[1].substring(pair[1].lastIndexOf('/') + 1,
		    pair[1].length());

	    // Avoid including DC, RELS-EXT or RELS-INT datastreams
	    if (isReservedDatastream(idData)) {
		continue;
	    }
	    // compose the datastream identifier string, i.e.
	    // objectID:005/datastream_name
	    arrayId.add(pair[0] + ";" + idData);
	}
	performGetDataStream(mulgObject, fedObject, arrayId, graphName);
    }

    /**
     * Returns the generated Mulgara graph URI
     * 
     * @return string containing the generated Mulgara graph for a given
     *         collection
     */
    public String getGraphURL() {
	return this.mulgObject.getHttpMan().getGraphURL();
    }

    /**
     * Deletes a graph from the given mulgara instance
     * 
     * @param graphURL
     *            the URI of the graph to delete
     */
    public boolean dropGraph(String graphURL) {
	try {
	    MulgaraGraphService mgservice = new MulgaraGraphServiceImpl();
	    MulgaraOpResults mopres = mgservice.dropGraph(graphURL);
	    if (mopres.isOperationResults())
		return true;
	    else
		return false;
	} catch (uk.ljmu.mulgaraifz.mulgarainference.exceptions.MulgaraException e) {
	    log.fatal(e.getMessage());
	    return false;
	} catch (QueryException e) {
	    log.fatal(e.getMessage());
	    return false;
	}
    }

    // PRIVATE METHODS
    /**
     * 
     * @param mulgObj
     * @param fedObj
     * @param arrayID
     * @param graphName
     * @throws FedoraException
     */
    private void performGetDataStream(MulgaraOperations mulgObj,
	    FedoraOperationsAPIM fedObj, ArrayList<String> arrayID,
	    String graphName) throws FedoraException {
	int i = 0;
	boolean result = false;

	while (i < arrayID.size()) {
	    if (arrayID.get(i) == null) {
		i++;
		continue;
	    }
	    String[] pair = arrayID.get(i).split(";");
	    i++;
	    // REQUEST TO FEDORA API
	    String responseString = "";
	    String controlGroup = "";

	    // JUST RETRIEVE INLINE DATASTREAMS
	    // DUE TO FEDORA NEW VERSIONS MIMETYPE MANAGEMENT
	    // IF WE HAVE AN EXTERNAL DATASTREAM WITH TYPE TEXT/XML WILL BE
	    // TREATED AS INLINE XML
	    try {
		controlGroup = fedObj.getDatastreamControlGroup(pair[0], // pid
			pair[1], // DS ID
			"xml", // format of response
			"", // asOfDatetime
			""); // validatechecksum
	    } catch (Exception e1) {
		log.fatal(e1.getMessage());
		throw new FedoraException(e1.getMessage());
	    }
	    if (controlGroup.equalsIgnoreCase("X"))// We ignore datastreams that
	    // are not inline XML or RDF
	    {
		// Check if the datastream contents are valid RDF, because it
		// could be plain XML
		// IMPLEMENTATION PENDING
		try {
		    responseString = fedObj.getDatastreamContent(pair[0], // pid
			    pair[1] // DS ID
			    ); // validatechecksum
		} catch (Exception e) {
		    log.fatal(e.getMessage());
		    throw new FedoraException(e.getMessage());
		}
		// REQUEST TO MULGARA TO LOAD RDF FILES
		// Check Implementation of PostMulgaraRequest
		result = mulgObj.getHttpMan().httpPostMulgaraRequest(
			responseString, graphName);
		GraphInformation auxGraph = new GraphInformation(graphName,
			mulgObj.getHttpMan().getPostOpHeaders());
		auxGraph.setSourceObjectId(pair[0]);
		auxGraph.setDsName(pair[1]);
		this.graphInfo.add(auxGraph);
		log.info("Datastream " + pair[1] + " uploaded with results "
			+ result);
	    }
	}
    }

    private boolean isReservedDatastream(String dsName) {
	if (dsName.equals(RESERVED_PREFIXES.get("DC"))
		|| dsName.equals(RESERVED_PREFIXES.get("EXT"))
		|| dsName.equals(RESERVED_PREFIXES.get("INT"))) {
	    return true;
	} else
	    return false;
    }

    /**
     * 
     * @param mulgObj
     * @param collectionId
     * @return
     * @throws JFigException
     * @throws MulgaraException
     * @throws GraphException
     */
    public List<String> getLoopIDbyCollection(MulgaraOperations mulgObj,
	    String collectionId) throws JFigException, MulgaraException,
	    GraphException {
	List<String> mList = new ArrayList<String>();
	String strBody[];

	String query = QueryConstants.LOOP_GET_IDS_BY_COLLECTION;
	String constantValue = "";

	constantValue = JFig.getInstance().getValue("mulgaraServer", "GRAPH");

	if (!constantValue.startsWith("<"))
	    constantValue = Constants.URI_BEGIN + constantValue
		    + Constants.URI_END;
	String ns = collectionId.substring(collectionId.indexOf('/') + 1,
		collectionId.lastIndexOf(':'));
	query = QueryConstants.parseQuery(query, "GRAPH", constantValue);
	query = QueryConstants.parseQuery(query, "COL_ID", collectionId
		.startsWith(MetadataUtilities.OBJECTID) ? collectionId
		: MetadataUtilities.OBJECTID + collectionId);
	query = QueryConstants.parseQuery(query, "COL_NS", ns);
	String format = mulgObj.getHttpMan().get_OutputFormats().get("xml");
	strBody = mulgObj.getHttpMan().httpSparqlQuery(query, format);

	// Obtain XML document from results
	Iterator<?> iterator = XmlTraverse.createSparqlXMLIterator(strBody[0]);

	if (iterator != null && iterator.hasNext()) {
	    while (iterator.hasNext()) {
		// Obtain the list of 'binding' elements as a sibling node of
		// 'result'
		// For each element 'result' the first binding node is the
		// object identifier
		// the second binding element is the data stream name
		/*
		 * <result> <binding name="s"> <uri>info:fedora/demo:224</uri>
		 * </binding> <binding name="o"> <literal> DS_NAME </literal>
		 * </binding> </result>
		 */
		List<?> bindList = ((Element) iterator.next()).elements();
		Element bind = (Element) bindList.get(0);
		// FEDORA ID
		Element insideBind = (Element) bind.elements().get(0);
		String idData = insideBind.getText();
		bind = (Element) bindList.get(1);
		// DATASTREAM NAME
		insideBind = (Element) bind.elements().get(0);
		String dsName = insideBind.getText();
		mList.add(idData + ";" + dsName);
	    }
	} else {
	    throw new GraphException("No results from Mulgara query: " + query);
	}

	return mList;
    }

    /**
     * @param qudexCollectionPid
     * @return List<String>
     */
    public List<String> retrieveDependantQudexDocuments(
	    String qudexCollectionPid) {
	List<String> mList = new ArrayList<String>();
	String strBody[];

	try {

	    String query = QueryConstants.QUDEX_GET_DEPENDANT_FILES;
	    String constantValue = "";

	    constantValue = JFig.getInstance().getValue("mulgaraServer",
		    "GRAPH");

	    if (!constantValue.startsWith(Constants.URI_BEGIN))
		constantValue = Constants.URI_BEGIN + constantValue
			+ Constants.URI_END;
	    query = QueryConstants.parseQuery(query, "GRAPH", constantValue);
	    query = QueryConstants
		    .parseQuery(
			    query,
			    "COL_ID",
			    qudexCollectionPid
				    .startsWith(MetadataUtilities.OBJECTID) ? qudexCollectionPid
				    : MetadataUtilities.OBJECTID
					    + qudexCollectionPid);
	    String format = mulgObject.getHttpMan().get_OutputFormats().get(
		    "xml");
	    strBody = mulgObject.getHttpMan().httpSparqlQuery(query, format);

	    // Obtain XML document from results
	    Iterator<?> iterator = XmlTraverse
		    .createSparqlXMLIterator(strBody[0]);

	    if (iterator != null && iterator.hasNext()) {
		while (iterator.hasNext()) {
		    List<?> bindList = ((Element) iterator.next()).elements();
		    Element bind = (Element) bindList.get(0);
		    // FEDORA ID
		    Element insideBind = (Element) bind.elements().get(0);
		    String idData = insideBind.getText();

		    mList.add(idData);
		}
	    } else {
		log.info("Qudex collection without documents associated");
		return mList;
	    }

	    return mList;
	} catch (MulgaraException e) {
	    log.error("Error in retrieveDependantQudexDocuments: ", e);
	    return null;
	} catch (JFigException e) {
	    log.error("Error in retrieveDependantQudexDocuments: ", e);
	    return null;
	} finally {
	    if (mulgObject != null)
		mulgObject.mulgaraFinaliseHttpConnections();
	}
    }

    /**
     * @param collectionsPrefix
     * @return List<String>
     */
    public List<String> retrieveQudexCollections(String collectionsPrefix, String collectionId) {
	List<String> mList = new ArrayList<String>();
	String strBody[];

	try {

	    String query = GET_QUDEX_COLLECTIONS_WORKING;
	    String constantValue = "";

	    constantValue = JFig.getInstance().getValue("mulgaraServer",
		    "GRAPH");

	    if (!constantValue.startsWith(Constants.URI_BEGIN))
		constantValue = Constants.URI_BEGIN + constantValue
			+ Constants.URI_END;
	    query = QueryConstants.parseQuery(query, "GRAPH", constantValue);
	    
	    if (!collectionId.contains(MetadataUtilities.OBJECTID)) {
			if (!collectionId.startsWith(Constants.URI_BEGIN)) {
			    collectionId = Constants.URI_BEGIN
				    + MetadataUtilities.OBJECTID + collectionId
				    + Constants.URI_END;
			} else {
			    String auxStr = collectionId.replace(Constants.URI_BEGIN,
				    "").replace(Constants.URI_END, "");
			    collectionId = Constants.URI_BEGIN
				    + MetadataUtilities.OBJECTID + auxStr
				    + Constants.URI_END;
			}
		    } else if (!collectionId.startsWith(Constants.URI_BEGIN)) {
			collectionId = Constants.URI_BEGIN + collectionId
				+ Constants.URI_END;
		    }
	    query = QueryConstants.parseQuery(query, "WORKCOL", collectionId);
	    query = QueryConstants.parseQuery(query, "PREFIX",
		    collectionsPrefix);
	    String format = mulgObject.getHttpMan().get_OutputFormats().get(
		    "xml");
	    strBody = mulgObject.getHttpMan().httpSparqlQuery(query, format);

	    // Obtain XML document from results
	    Iterator<?> iterator = XmlTraverse
		    .createSparqlXMLIterator(strBody[0]);

	    if (iterator != null && iterator.hasNext()) {
		while (iterator.hasNext()) {
		    List<?> bindList = ((Element) iterator.next()).elements();
		    Element bind = (Element) bindList.get(0);
		    // FEDORA ID
		    Element insideBind = (Element) bind.elements().get(0);
		    String idData = insideBind.getText();
		    // FEDORA Title
		    bind = (Element) bindList.get(1);
		    String title = "";
		    if (bind == null)
			title = "Title not available for PID: "
			    + idData;
		    else {
			insideBind = (Element) bind.elements().get(0);
			title = insideBind.getText() != "" ? insideBind
			    .getText() : "Title not available for PID: "
			    + idData; 
		    }
		    mList.add(idData + ";" + title);
		}
	    } else {
		log.info("No Qudex Collections in the Repository");
		return mList;
	    }

	    return mList;
	} catch (MulgaraException e) {
	    log.error("Error in retrieveQudexCollections: ", e);
	    return null;
	} catch (JFigException e) {
	    log.error("Error in retrieveQudexCollections: ", e);
	    return null;
	} finally {
	    if (mulgObject != null)
		mulgObject.mulgaraFinaliseHttpConnections();
	}
    }

    /**
     * Returns whether a given collection is a sub-collection or a parent
     * collection
     * 
     * @param collectionId
     *            Fedora PID of the collection to find
     * @return true if the collection is a sub-collection, false otherwise
     * @throws MulgaraException
     */
    public boolean isSubCollection(String collectionId) throws MulgaraException {
	String strBody[];

	try {
	    String query = GET_QUDEX_IS_SUBCOLLECTION;
	    String constantValue = "";

	    constantValue = JFig.getInstance().getValue("mulgaraServer",
		    "GRAPH");

	    if (!constantValue.startsWith(Constants.URI_BEGIN))
		constantValue = Constants.URI_BEGIN + constantValue
			+ Constants.URI_END;

	    if (!collectionId.contains(MetadataUtilities.OBJECTID)) {
		if (!collectionId.startsWith(Constants.URI_BEGIN)) {
		    collectionId = Constants.URI_BEGIN
			    + MetadataUtilities.OBJECTID + collectionId
			    + Constants.URI_END;
		} else {
		    String auxStr = collectionId.replace(Constants.URI_BEGIN,
			    "").replace(Constants.URI_END, "");
		    collectionId = Constants.URI_BEGIN
			    + MetadataUtilities.OBJECTID + auxStr
			    + Constants.URI_END;
		}
	    } else if (!collectionId.startsWith(Constants.URI_BEGIN)) {
		collectionId = Constants.URI_BEGIN + collectionId
			+ Constants.URI_END;
	    }

	    query = QueryConstants.parseQuery(query, "GRAPH", constantValue);
	    query = QueryConstants.parseQuery(query, "COL_ID", collectionId);
	    String format = mulgObject.getHttpMan().get_OutputFormats().get(
		    "xml");
	    strBody = mulgObject.getHttpMan().httpSparqlQuery(query, format);

	    // Obtain XML document from results
	    Document doc = DocumentHelper.parseText(strBody[0]);
	    
	    if (doc == null) {
		log.error("Error in isSubCollection: parsing xml query results");
		throw new MulgaraException("Errors while in isSubCollection query");
	    }
	    Element booleanResponse = doc.getRootElement().element("boolean");
	    
	    if (booleanResponse != null) 
		return Boolean.parseBoolean(booleanResponse.getText());
	    else return false;
	   } catch (MulgaraException e) {
	    log.error("Error in isSubCollection: ", e);
	    throw new MulgaraException("Errors while in isSubCollection query");
	} catch (JFigException e) {
	    log.error("Error in isSubCollection: ", e);
	    throw new MulgaraException("Errors while in isSubCollection query");
	} catch (DocumentException e) {
	    log.error("Error in isSubCollection: ", e);
	    throw new MulgaraException("Errors while in isSubCollection query");
	} //finally {
	    //if (mulgObject != null)
	    //mulgObject.mulgaraFinaliseHttpConnections();
	//}
    }

    public void destroy() {
	if (this.fedObject != null) {
	    this.fedObject.closeHttpConnections();
	}
	if (this.mulgObject != null) {
	    this.mulgObject.mulgaraFinaliseHttpConnections();
	}
    }

    /**
     * @param startingCollection
     * @throws MulgaraException
     */
    public void findRootCollection(String startingCollection)
	    throws MulgaraException {
	String resultsQuery;

	resultsQuery = this.retrieveSubcollectionParent(startingCollection);
	if (resultsQuery != null) {
	    // Recursive bit
	    this.findRootCollection(resultsQuery);
	} else {
	    this.rootCollectionPid = startingCollection;
	}
    }

    private String retrieveSubcollectionParent(String collectionId)
	    throws MulgaraException {
	String strBody[];

	try {
	    String query = GET_IMMEDIATE_COLLECTION_PARENT;
	    String constantValue = "";

	    constantValue = JFig.getInstance().getValue("mulgaraServer",
		    "GRAPH");

	    if (!constantValue.startsWith(Constants.URI_BEGIN))
		constantValue = Constants.URI_BEGIN + constantValue
			+ Constants.URI_END;

	    if (!collectionId.contains(MetadataUtilities.OBJECTID)) {
		if (!collectionId.startsWith(Constants.URI_BEGIN)) {
		    collectionId = Constants.URI_BEGIN
			    + MetadataUtilities.OBJECTID + collectionId
			    + Constants.URI_END;
		} else {
		    String auxStr = collectionId.replace(Constants.URI_BEGIN,
			    "").replace(Constants.URI_END, "");
		    collectionId = Constants.URI_BEGIN
			    + MetadataUtilities.OBJECTID + auxStr
			    + Constants.URI_END;
		}
	    } else if (!collectionId.startsWith(Constants.URI_BEGIN)) {
		collectionId = Constants.URI_BEGIN + collectionId
			+ Constants.URI_END;
	    }

	    query = QueryConstants.parseQuery(query, "GRAPH", constantValue);
	    query = QueryConstants.parseQuery(query, "COL_ID", collectionId);
	    String format = mulgObject.getHttpMan().get_OutputFormats().get(
		    "xml");
	    strBody = mulgObject.getHttpMan().httpSparqlQuery(query, format);

	    // Obtain XML document from results
	    Iterator<?> iterator = XmlTraverse
		    .createSparqlXMLIterator(strBody[0]);

	    if (iterator.hasNext()) {
		List<?> bindList = ((Element) iterator.next()).elements();
		Element bind = (Element) bindList.get(0);
		Element insideBind = (Element) bind.elements().get(0);
		String idData = insideBind.getText();
		return idData;
	    } else
		return null;
	} catch (MulgaraException e) {
	    log.error("Error in retrieveSubcollectionParent: ", e);
	    throw new MulgaraException(
		    "Errors while in retrieveSubcollectionParent query");
	} catch (JFigException e) {
	    log.error("Error in retrieveSubcollectionParent: ", e);
	    throw new MulgaraException(
		    "Errors while in retrieveSubcollectionParent query");
	}
    }
    // AMG - COLLECTIONS/SUB-COLLECTIONS TREE GENERATION
    /**
     * @param collectionsPrefix
     * @return List<String>
     */
    public Iterator<?> retrieveQudexCollectionsOneQuery(String collectionsPrefix) {
	String strBody[];

	try {

	    String query = GET_COLLECTIONS_ONE_QUERY;
	    String constantValue = "";

	    constantValue = JFig.getInstance().getValue("mulgaraServer",
		    "GRAPH");

	    if (!constantValue.startsWith(Constants.URI_BEGIN))
		constantValue = Constants.URI_BEGIN + constantValue
			+ Constants.URI_END;
	    query = QueryConstants.parseQuery(query, "GRAPH", constantValue);
	    query = QueryConstants.parseQuery(query, "PREFIX",
		    collectionsPrefix);
	    String format = mulgObject.getHttpMan().get_OutputFormats().get(
		    "xml");
	    strBody = mulgObject.getHttpMan().httpSparqlQuery(query, format);

	    // Obtain XML document from results
	    Iterator<?> iterator = XmlTraverse
		    .createSparqlXMLIterator(strBody[0]);

	    if (iterator != null && iterator.hasNext()) {
		return iterator;
	    } else {
		log.info("No Qudex Collections in the Repository");
		return null;
	    }
	} catch (MulgaraException e) {
	    log.error("Error in retrieveQudexCollectionsOneQuery: ", e);
	    return null;
	} catch (JFigException e) {
	    log.error("Error in retrieveQudexCollectionsOneQuery: ", e);
	    return null;
	} finally {
	    if (mulgObject != null)
		mulgObject.mulgaraFinaliseHttpConnections();
	}
    }
    public List<CollectionElement> constructCollectionsTree(String prefix) {
	List<CollectionElement> treeList = new ArrayList<CollectionElement>();
	boolean add = false;
	// Query Mulgara to obtain collections list
	Iterator<?> it = this.retrieveQudexCollectionsOneQuery(prefix);
	// Parse iterator and construct tree structure
	if (it != null) {
	    try {
		if (it.hasNext())
		    log.debug("ITERATOR HAS ELEMENTS");
		while (it.hasNext()) {
		    String parent = "", child = "", title = "";
		    // Iterate over result elements
		    Node result = (Element) it.next();
		    // FEDORA ID
		    Element idElement = (Element) result.selectNodes("child::*[@name='id']").get(0);
		    Element insideBind = (Element) idElement.elements().get(0);
		    String idData = insideBind.getText();
		    //id, col and child are the variables bound in the Sparql query
		    Element parentElement = (Element) result
			    .selectSingleNode("child::*[@name='col']");
		    if (parentElement != null) {
			// FEDORA collection parent
			insideBind = (Element) parentElement.elements().get(0);
			parent = insideBind.getText();
		    }
		    Element childElement = (Element) result
			    .selectSingleNode("child::*[@name='child']");
		    if (childElement != null) {
			// FEDORA collection child
			insideBind = (Element) childElement.elements().get(0);
			child = insideBind.getText();
		    }
		    Element titleElement = (Element) result
			    .selectSingleNode("child::*[@name='title']");
		    if (titleElement != null) {
			// FEDORA collection title
			insideBind = (Element) titleElement.elements().get(0);
			title = insideBind.getText();
		    }
		    CollectionElement auxElem = CollectionElement.findElement(
			    idData, treeList);
		    if (auxElem == null) {
			add = true;
			auxElem = new CollectionElement();
			auxElem.setCollectionId(idData);
		    }
		    if (parent == "") {
			auxElem.setRootCollection(true);
		    } else {
			auxElem.setRootCollection(false);
			auxElem.getImmediateParents().add(parent.replace(MetadataUtilities.OBJECTID, ""));
		    }
		    if (child != "") {
			auxElem.getImmediateChildren().add(child.replace(MetadataUtilities.OBJECTID, ""));
		    }
		    if (title != "") {
			auxElem.setCollectionTitle(title);
		    } else {
			auxElem
				.setCollectionTitle("Title not available for collection with ID: "
					+ idData);
		    }
		    if (add) {
			add =false;
			treeList.add(auxElem);
			log.debug(auxElem.getCollectionTitle());
		    }
		}		
	    }
	    catch (Exception ex) {
		log.error("Error in constructCollectionsTree: ", ex);
	    }
	} else {
	    log.debug("NO ELEMENTS IN ITERATOR");
	}

	return treeList;	
    }

    public String getCollectionRootParent(String collectionId, String prefix) {
	String strBody[];

	try {

	    String query = GET_QUDEX_SUBCOLLECTION_ROOT_PARENT;
	    String constantValue = "";

	    constantValue = JFig.getInstance().getValue("mulgaraServer",
		    "GRAPH");

	    if (!constantValue.startsWith(Constants.URI_BEGIN))
		constantValue = Constants.URI_BEGIN + constantValue
			+ Constants.URI_END;
	    if (!collectionId.startsWith(MetadataUtilities.OBJECTID)) {
		collectionId = Constants.URI_BEGIN + MetadataUtilities.OBJECTID + collectionId
		+ Constants.URI_END;
	    }
	    query = QueryConstants.parseQuery(query, "COL_ID", collectionId);
	    query = QueryConstants.parseQuery(query, "GRAPH", constantValue);
	    query = QueryConstants.parseQuery(query, "PREFIX",
		    prefix);
	    String format = mulgObject.getHttpMan().get_OutputFormats().get(
		    "xml");
	    strBody = mulgObject.getHttpMan().httpSparqlQuery(query, format);

	    // Obtain XML document from results
	    Iterator<?> iterator = XmlTraverse
		    .createSparqlXMLIterator(strBody[0]);

	    if (iterator.hasNext()) {
		List<?> bindList = ((Element) iterator.next()).elements();
		Element bind = (Element) bindList.get(0);
		Element insideBind = (Element) bind.elements().get(0);
		String idData = insideBind.getText();
		return idData;
	    } else return null; //Root Collection
	} catch (MulgaraException e) {
	    log.error("Error in getCollectionRootParent: ", e);
	    return null;
	} catch (JFigException e) {
	    log.error("Error in getCollectionRootParent: ", e);
	    return null;
	} finally {
	    if (mulgObject != null)
		mulgObject.mulgaraFinaliseHttpConnections();
	}
    }
    
    // CLEAN METHODS
    public void cleanInstance() {
	this.fedObject.closeHttpConnections();
	this.mulgObject.mulgaraFinaliseHttpConnections();
    }

	public List<String> retrieveQudexRootCollections(String qudexPrefix) {
		List<String> mList = new ArrayList<String>();
		String strBody[];

		try {

		    String query = GET_QUDEX_ROOTCOLLECTIONSTITLE;
		    String constantValue = "";

		    constantValue = JFig.getInstance().getValue("mulgaraServer",
			    "GRAPH");

		    if (!constantValue.startsWith(Constants.URI_BEGIN))
			constantValue = Constants.URI_BEGIN + constantValue
				+ Constants.URI_END;
		    query = QueryConstants.parseQuery(query, "GRAPH", constantValue);
		    query = QueryConstants.parseQuery(query, "PREFIX",
		    		qudexPrefix);
		    String format = mulgObject.getHttpMan().get_OutputFormats().get(
			    "xml");
		    strBody = mulgObject.getHttpMan().httpSparqlQuery(query, format);

		    // Obtain XML document from results
		    Iterator<?> iterator = XmlTraverse
			    .createSparqlXMLIterator(strBody[0]);

		    if (iterator != null && iterator.hasNext()) {
			while (iterator.hasNext()) {
			    List<?> bindList = ((Element) iterator.next()).elements();
			    Element bind = (Element) bindList.get(0);
			    // FEDORA ID
			    Element insideBind = (Element) bind.elements().get(0);
			    String idData = insideBind.getText();
			    // TODO UNCOMMENT THIS
			    //boolean isInstance = this.collectionContainsInstance(idData);
			    //if (isInstance)
			    //	continue;
			    // FEDORA Title
			    bind = (Element) bindList.get(1);
			    String title = "";
			    if (bind == null)
				title = "Title not available for PID: "
				    + idData;
			    else {
				insideBind = (Element) bind.elements().get(0);
				title = insideBind.getText() != "" ? insideBind
				    .getText() : "Title not available for PID: "
				    + idData; 
			    }
			    mList.add(idData + ";" + title);
			}
		    } else {
			log.info("No Qudex Collections in the Repository");
			return mList;
		    }

		    return mList;
		} catch (MulgaraException e) {
		    log.error("Error in retrieveQudexCollections: ", e);
		    return null;
		} catch (JFigException e) {
		    log.error("Error in retrieveQudexCollections: ", e);
		    return null;
		} finally {
		    if (mulgObject != null)
			mulgObject.mulgaraFinaliseHttpConnections();
		}
	}
	
	public boolean collectionContainsInstance(String collectionId) throws MulgaraException {
		String strBody[];

		try {
		    String query = QUDEX_CONTAINS_INSTANCE;
		    String constantValue = "";

		    constantValue = JFig.getInstance().getValue("mulgaraServer",
			    "GRAPH");

		    if (!constantValue.startsWith(Constants.URI_BEGIN))
			constantValue = Constants.URI_BEGIN + constantValue
				+ Constants.URI_END;

		    if (collectionId.startsWith(Constants.URI_BEGIN))
		    	collectionId = collectionId.replace(Constants.URI_BEGIN, "").replace(Constants.URI_END, "");
		    
		    if (!collectionId.contains(MetadataUtilities.OBJECTID)) {
			    collectionId = MetadataUtilities.OBJECTID + collectionId;
		    }

		    query = QueryConstants.parseQuery(query, "GRAPH", constantValue);
		    query = QueryConstants.parseQuery(query, "COLID", collectionId);
		    String format = mulgObject.getHttpMan().get_OutputFormats().get(
			    "xml");
		    strBody = mulgObject.getHttpMan().httpSparqlQuery(query, format);

		    // Obtain XML document from results
		    Document doc = DocumentHelper.parseText(strBody[0]);
		    
		    if (doc == null) {
			log.error("Error in collectionContainsInstance: parsing xml query results");
			throw new MulgaraException("Errors while in collectionContainsInstance query");
		    }
		    Element booleanResponse = doc.getRootElement().element("boolean");
		    
		    if (booleanResponse != null) 
			return Boolean.parseBoolean(booleanResponse.getText());
		    else return false;
		   } catch (MulgaraException e) {
		    log.error("Error in collectionContainsInstance: ", e);
		    throw new MulgaraException("Errors while in collectionContainsInstance query");
		} catch (JFigException e) {
		    log.error("Error in isSubCollection: ", e);
		    throw new MulgaraException("Errors while in collectionContainsInstance query");
		} catch (DocumentException e) {
		    log.error("Error in isSubCollection: ", e);
		    throw new MulgaraException("Errors while in collectionContainsInstance query");
		}
	}

	public List<String> retrieveQudexInstanceCollections(String qudexPrefix) {
		List<String> mList = new ArrayList<String>();
		String strBody[];

		try {

		    String query = GET_QUDEX_ROOTCOLLECTIONSTITLE;
		    String constantValue = "";

		    constantValue = JFig.getInstance().getValue("mulgaraServer",
			    "GRAPH");

		    if (!constantValue.startsWith(Constants.URI_BEGIN))
			constantValue = Constants.URI_BEGIN + constantValue
				+ Constants.URI_END;
		    query = QueryConstants.parseQuery(query, "GRAPH", constantValue);
		    query = QueryConstants.parseQuery(query, "PREFIX",
		    		qudexPrefix);
		    String format = mulgObject.getHttpMan().get_OutputFormats().get(
			    "xml");
		    strBody = mulgObject.getHttpMan().httpSparqlQuery(query, format);

		    // Obtain XML document from results
		    Iterator<?> iterator = XmlTraverse
			    .createSparqlXMLIterator(strBody[0]);

		    if (iterator != null && iterator.hasNext()) {
			while (iterator.hasNext()) {
			    List<?> bindList = ((Element) iterator.next()).elements();
			    Element bind = (Element) bindList.get(0);
			    // FEDORA ID
			    Element insideBind = (Element) bind.elements().get(0);
			    String idData = insideBind.getText();
			    boolean isInstance = this.collectionContainsInstance(idData);
			    if (!isInstance)
			    	continue;
			    // FEDORA Title
			    bind = (Element) bindList.get(1);
			    String title = "";
			    if (bind == null)
				title = "Title not available for PID: "
				    + idData;
			    else {
				insideBind = (Element) bind.elements().get(0);
				title = insideBind.getText() != "" ? insideBind
				    .getText() : "Title not available for PID: "
				    + idData; 
			    }
			    mList.add(idData + ";" + title);
			}
		    } else {
			log.info("No Qudex Collections in the Repository");
			return mList;
		    }

		    return mList;
		} catch (MulgaraException e) {
		    log.error("Error in retrieveQudexInstanceCollections: ", e);
		    return null;
		} catch (JFigException e) {
		    log.error("Error in retrieveQudexInstanceCollections: ", e);
		    return null;
		} finally {
		    if (mulgObject != null)
			mulgObject.mulgaraFinaliseHttpConnections();
		}
	}

	public List<String> retrieveQudexCollectionFiles(String collectionId) {
		List<String> mList = new ArrayList<String>();
		String strBody[];

		try {

		    String query = QUDEX_GET_FILES;
		    String constantValue = "";

		    constantValue = JFig.getInstance().getValue("mulgaraServer",
			    "GRAPH");

		    if (!constantValue.startsWith(Constants.URI_BEGIN))
			constantValue = Constants.URI_BEGIN + constantValue
				+ Constants.URI_END;
		    query = QueryConstants.parseQuery(query, "GRAPH", constantValue);
		    
		    String temp;
		    if (!collectionId.contains(FEDORA_ID_PREFIX)) {
			    temp = FEDORA_ID_PREFIX + "/" + collectionId;
			} else
			    temp = collectionId;
		    query = QueryConstants.parseQuery(query, "COL_ID",
		    		temp);
		    String format = mulgObject.getHttpMan().get_OutputFormats().get(
			    "xml");
		    strBody = mulgObject.getHttpMan().httpSparqlQuery(query, format);

		    // Obtain XML document from results
		    Iterator<?> iterator = XmlTraverse
			    .createSparqlXMLIterator(strBody[0]);

		    if (iterator != null && iterator.hasNext()) {
			while (iterator.hasNext()) {
			    List<?> bindList = ((Element) iterator.next()).elements();
			    Element bind = (Element) bindList.get(0);
			    // FEDORA ID
			    Element insideBind = (Element) bind.elements().get(0);
			    String idData = insideBind.getText();
			    // TODO UNCOMMENT THIS
			    //boolean isInstance = this.collectionContainsInstance(idData);
			    //if (isInstance)
			    //	continue;
			    // FEDORA Title
			    bind = (Element) bindList.get(1);
			    String title = "";
			    if (bind == null)
				title = "Title not available for PID: "
				    + idData;
			    else {
				insideBind = (Element) bind.elements().get(0);
				title = insideBind.getText() != "" ? insideBind
				    .getText() : "Title not available for PID: "
				    + idData; 
			    }
			    mList.add(idData + ";" + title);
			}
		    } else {
			log.info("No Qudex Collections in the Repository");
			return mList;
		    }

		    return mList;
		} catch (MulgaraException e) {
		    log.error("Error in retrieveQudexCollections: ", e);
		    return null;
		} catch (JFigException e) {
		    log.error("Error in retrieveQudexCollections: ", e);
		    return null;
		} finally {
		    if (mulgObject != null)
			mulgObject.mulgaraFinaliseHttpConnections();
		}
	}

	public String retrieveObjectTitle(String fedoraPid) {
		String title = "";
		String strBody[];

		try {

		    String query = QUDEX_GET_OBJ_TITLE;
		    String constantValue = "";

		    constantValue = JFig.getInstance().getValue("mulgaraServer",
			    "GRAPH");

		    if (!constantValue.startsWith(Constants.URI_BEGIN))
			constantValue = Constants.URI_BEGIN + constantValue
				+ Constants.URI_END;
		    query = QueryConstants.parseQuery(query, "GRAPH", constantValue);
		    
		    String temp;
		    if (!fedoraPid.contains(FEDORA_ID_PREFIX)) {
			    temp = FEDORA_ID_PREFIX + "/" + fedoraPid;
			} else
			    temp = fedoraPid;
		    query = QueryConstants.parseQuery(query, "OBJ_ID",
		    		temp);
		    String format = mulgObject.getHttpMan().get_OutputFormats().get(
			    "xml");
		    strBody = mulgObject.getHttpMan().httpSparqlQuery(query, format);

		    // Obtain XML document from results
		    Iterator<?> iterator = XmlTraverse
			    .createSparqlXMLIterator(strBody[0]);

		    if (iterator != null && iterator.hasNext()) {
			while (iterator.hasNext()) {
			    List<?> bindList = ((Element) iterator.next()).elements();
			    Element bind = (Element) bindList.get(0);
			    // FEDORA TITLE
			    Element insideBind = (Element) bind.elements().get(0);
			    title = insideBind.getText();
			}
		    } else {
			log.info("Object not found in the repository");
			return title;
		    }

		    return title;
		} catch (MulgaraException e) {
		    log.error("Error in retrieveObjectTitle: ", e);
		    return null;
		} catch (JFigException e) {
		    log.error("Error in retrieveObjectTitle: ", e);
		    return null;
		} finally {
		    if (mulgObject != null)
			mulgObject.mulgaraFinaliseHttpConnections();
		}
	}
    /**
     * Returns the category PID for a collection category with a given category label
     * 
     * @param catLabel
     * @param collectionID
     * @return the Category PID
     * @throws MulgaraException
     */

	public String retrieveCategoryPID(String catLabel, String collectionID) {
		String PID = "";
		String strBody[];

		try {

		    String query = GET_CATEGORY_PID;
		    String constantValue = "";

		    constantValue = JFig.getInstance().getValue("mulgaraServer",
			    "GRAPH");

		    if (!constantValue.startsWith(Constants.URI_BEGIN))
			constantValue = Constants.URI_BEGIN + constantValue
				+ Constants.URI_END;
		    query = QueryConstants.parseQuery(query, "GRAPH", constantValue);
		    query = QueryConstants.parseQuery(query, "CAT_LABEL", catLabel);
		    query = QueryConstants.parseQuery(query, "COL_ID", collectionID);
		    query = QueryConstants.parseQuery(query, "COL_PREFIX", "qudex");
		    
		    String format = mulgObject.getHttpMan().get_OutputFormats().get(
			    "xml");
		    strBody = mulgObject.getHttpMan().httpSparqlQuery(query, format);

		    // Obtain XML document from results
		    Iterator<?> iterator = XmlTraverse
			    .createSparqlXMLIterator(strBody[0]);

		    if (iterator != null && iterator.hasNext()) {
			while (iterator.hasNext()) {
			    List<?> bindList = ((Element) iterator.next()).elements();
			    Element bind = (Element) bindList.get(0);
			    // FEDORA PID
			    Element insideBind = (Element) bind.elements().get(0);
			    PID = insideBind.getText();
			}
		    } else {
			log.info("Object not found in the repository");
			return PID;
		    }

		    return PID;
		} catch (MulgaraException e) {
		    log.error("Error in retrieveObjectTitle: ", e);
		    return null;
		} catch (JFigException e) {
		    log.error("Error in retrieveObjectTitle: ", e);
		    return null;
		} finally {
		    if (mulgObject != null)
			mulgObject.mulgaraFinaliseHttpConnections();
		}
	}
	/**
	 * Checks whether Mulgara service is up and running
	 * 
	 * @return true is Mulgara is up and running; false otherwise
	 */
	public boolean isMulgaraRunning() {	
		if (mulgObject != null) {
			return mulgObject.isMulgaraRunning();
		}
		return false;
	}
	
	/**
	 * Checks whether Fedora service is up and running
	 * 
	 * @return true is Fedora is up and running; false otherwise
	 */
	public boolean isFedoraRunning() {	
		if (fedObject != null) {
			String results = fedObject.getNextPID();
			if (results != null)
				return true; 
		}
		return false;
	}
}
